import { Injectable } from '@nestjs/common'
import { AcrossService } from 'src/across/across.service'
import { BetService } from 'src/bet/bet.service'
import { OtherService } from 'src/other/other.service'
import { PrismaService } from 'src/prisma/prisma.service'
import { TowerService } from 'src/tower/tower.service'
import { WireService } from 'src/wire/wire.service'
import { CreateSectionDto } from './dto/create-section.dto'
import { UpdateSectionDto } from './dto/update-section.dto'
import { calcAcrossPower, calceOrBet, calcHandAngle, calcMaxPh, calcMaxTi, calcSpan, calcTowerPh } from './utils/calc'
import { CalcXY } from './utils/CalcXY'

@Injectable()
export class SectionService {
  constructor(
    private prisma: PrismaService,
    private tower: TowerService,
    private bet: BetService,
    private across: AcrossService,
    private wire: WireService,
    private other: OtherService,
  ) {}

  // 创建区段
  async create(createSectionDto: CreateSectionDto) {
    return await this.prisma.section.create({
      data: {
        name: createSectionDto.name,
        projId: +createSectionDto.projId,
      },
    })
  }

  async findAll(args: Record<string, any>) {
    const { projId } = args
    return await this.prisma.section.findMany({ where: { projId: +projId } })
  }

  /**
   * 这是该区段计算的总开关
   * @param id 区段的id
   */
  async calcP(args: Record<string, any>) {
    const { sectionId } = args

    // 判断sectionId是否存在?
    if (!sectionId) return '没有sectionId参数!'

    const section = await this.findOne(+sectionId)

    // 获取tower及bet的集合并计算
    const towers = await this.prisma.tower.findMany({ where: { sectionId: +sectionId } })
    const bets = await this.prisma.bet.findMany({ where: { sectionId: +sectionId } })
    const across = await this.prisma.across.findMany({ where: { sectionId: +sectionId } })

    const wires = await this.wire.findAll({ sectionId })
    const others = await this.other.findAll({ sectionId })

    // 获取引绳的参数
    const wire_dx = wires.find((w) => w.wireName.includes('导线'))
    const wire_big = wires.find((w) => w.wireName.includes('大引绳'))
    const wire_small = wires.find((w) => w.wireName.includes('小引绳'))
    const other_mozuxishu = others.find((o) => o.otherName.includes('摩'))

    const w = wire_big.wireWeight
    const e = other_mozuxishu.otherNum

    calcSpan(towers, bets)
    calcHandAngle(towers, bets)
    calceOrBet(bets, e) // 计算控制点ti的中间变量
    calcAcrossPower(towers, bets, across, w, e)
    calcMaxTi(across, section)
    calcTowerPh(towers, bets, section, w, e)
    calcMaxPh(towers, section)

    const caclXY = new CalcXY(section, towers, bets, across)
    caclXY.calcTowersXY()
    caclXY.calcAcrosssXY()
    caclXY.calcWidthAndHeight()
    caclXY.calcCurveXYs(w)

    // 更新tower的数据
    for (const tower of towers) {
      await this.tower.update(tower.id, { ...tower })
    }

    for (const a of across) {
      await this.across.update(a.id, {
        Fi: a.Fi,
        Hi: a.Hi,
        Ti: a.Ti,
        xy: a.xy,
        finalControl: a.finalControl,
      })
    }

    // 更新bet的数据
    for (const bet of bets) {
      await this.bet.update(bet.id, {
        btName: bet.btName,
        angle: bet.angle,
        btSpan: bet.btSpan,
        h: bet.h,
        eh: bet.eh,
        curvexy: bet.curvexy,
        sectionId: bet.sectionId,
      })
    }

    await this.update(+sectionId, {
      minXY: section.minXY,
      maxXY: section.maxXY,
    })
    return '成功'
  }

  /**
   * 负责计算tower的坐标点
   * @param args towerId
   */
  async calcTowerPoints(args: Record<string, any>) {
    const { sectionId } = args

    const section = await this.findOne(+sectionId)
    const towers = await this.prisma.tower.findMany({ where: { sectionId: +sectionId } })
    const bets = await this.prisma.bet.findMany({ where: { sectionId: +sectionId } })
    const across = await this.prisma.across.findMany({ where: { sectionId: +sectionId } })

    // 计算累距
    calcSpan(towers, bets)
    const caclXY = new CalcXY(section, towers, bets, across)
    caclXY.calcTowersXY()

    // 更新tower的数据
    for (const tower of towers) {
      await this.tower.update(tower.id, { ...tower })
    }
    return '成功'
  }

  async findOne(id: number) {
    return await this.prisma.section.findFirst({
      where: { id },
      include: {
        proj: true,
      },
    })
  }

  async update(id: number, updateSectionDto: UpdateSectionDto) {
    return await this.prisma.section.update({ where: { id }, data: updateSectionDto })
  }

  async remove(id: number) {
    return await this.prisma.section.delete({ where: { id } })
  }
}
